












import time
import hmac
import hashlib
import json
import requests
from quant.markets import Functions
from quant.markets.functions import get_asset_value
from quant.accounts import Order
from quant.utils import logging, Timer2, catch_exception, LimitDict, Iota
from quant.const import *

from quant.exchanges.util import (spot_value_factor, RecentChecker2, AscendingChecker, update_balance_default, prepare_placing,
                                  prepare_canceling, simulate_deal_spot, int_prec_to_precision)
from quant.exchanges.basics import ChannelBasic, HandlerBasic, ApiBasic, SpiBasic
# from quant.exchanges.gate_util import KucoinSocket, format_symbol, resume_symbol, is_welcome_data, build_req
from quant.markets.functions import get_contract_size


class KucoinSwapFunctions(Functions):
    def get_all_ticker(self):
        path = '/api/v1/contracts/active'
        url = rest_host + path

        response = self.session.get(url, timeout=3)
        if int(response.status_code) // 100 != 2:
            return {}
        j = response.json()

        result = {}
        _usdt = get_asset_value('usdt')

        for d in j['data']:
            contract = d['symbol']
            if not contract.endswith('USDTM'):
                continue

            symbol = resume_symbol(contract)
            result[symbol] = {
                'price': float(d['lastTradePrice']),
                'vol': float(d['turnoverOf24h']) * _usdt,
                'bid': None,
                'ask': None,
            }
        return result

    def get_recent_trade(self, symbol, _limit=None):
        path = '/api/v1/trade/history'
        url = '{}{}?symbol={}'.format(rest_host, path, format_symbol(symbol))

        response = self.session.get(url, timeout=3)
        if int(response.status_code) // 100 != 2:
            return {}
        j = response.json()

        result = [
            (
                d['sequence'],
                d['side'],
                float(d['price']),
                float(d['size']),
                float(str(d['ts'])[:13]) / 1000,
            )
            for d in j['data']
        ]
        result.reverse()
        return result

    def get_all_precision(self):
        path = '/api/v1/contracts/active'
        url = rest_host + path
        response = self.session.get(url, timeout=3)
        if int(response.status_code) // 100 != 2:
            return {}

        result = {}
        for d in response.json()['data']:
            contract = d['symbol']
            if not contract.endswith('USDTM'):
                continue

            symbol = resume_symbol(contract)
            price_unit = float_size_to_str(d['tickSize'])
            amount_unit = float_size_to_str(d['lotSize'])

            result[symbol] = (price_unit, amount_unit)
        return result

    def get_value_factor(self, symbol):
        contract_size = get_contract_size(Exchange.Kucoin, symbol)
        asset_value = get_asset_value(symbol.split('/')[0])
        return contract_size * asset_value

    def get_all_contract_size(self):
        path = '/api/v1/contracts/active'
        url = rest_host + path

        response = self.session.get(url, timeout=3)
        if int(response.status_code) // 100 != 2:
            return {}
        j = response.json()

        result = {}

        for d in j['data']:
            contract = d['symbol']
            if not contract.endswith('USDTM'):
                continue

            symbol = resume_symbol(contract)
            result[symbol] = float(d['multiplier'])
        return result

    def simulate_deal(self, order, deal_amount, mid_price, account):
        raise Exception()
        return simulate_deal_spot(order, deal_amount, mid_price, account)


def format_symbol(symbol):
    if symbol == 'btc/usdt.swap':
        return 'XBTUSDTM'

    contract = '{}USDTM'.format(symbol.split('/')[0].upper())
    return contract


def resume_symbol(contract):
    if contract == 'XBTUSDTM':
        return 'btc/usdt.swap'

    symbol = '{}/usdt.swap'.format(contract[:-5].lower())
    return symbol


def float_size_to_str(size):
    result = '{:f}'.format(size)
    result = result.rstrip('0')
    result = result.rstrip('.')
    return result


rest_host = 'https://api-futures.kucoin.com'
# ws_host = 'wss://api.gateio.ws/ws/v4/'


if __name__ == '__main__':
    import utils
    from quant.utils import perf_intv
    import keys
    from quant.markets import Markets, functions
    from quant.accounts import Accounts, Order
    from quant.utils import set_test_mode
    from utils import feed_test_raw, print_req
    set_test_mode()

    def try_channel():
        s = 'axs/usdt'
        mar = Markets()
        mar.add_market(Event.Book, Exchange.Kucoin, s, DataFrequency.Normal)
        mar.add_market(Event.Trade, Exchange.Kucoin, s, DataFrequency.Normal)

        # utils.print_book(mar)
        # utils.print_raw(mar)
        # utils.print_trades(mar)
        # utils.perf_raw_to_data(mar)
        # utils.check_raw_to_data_duplicate(mar)

        while True:
            input(':')

    def try_api():
        key = keys.get_key('gate_9293')
        account = Accounts().create_account('Kucoin', key)
        api = account.api

        # account.add_symbol('btc/usdt')
        account.info_engine.show_user_data()
        account.info_engine.show_problems()

        # api.query_balance()
        # api.query_all_balance()
        # api.query_open_orders('eth/usdt')
        # api.query_all_open_orders()

        # order = Order('eth/usdt', 'buy', 1, 1)
        # order = Order('doge/usdt', 'buy', 0.05, 21, order_type=OrderType.PostOnly)
        # api.place_order(order)

        api.add_symbol('doge/usdt')
        api.query_open_orders()
        api.query_open_orders()
        api.query_open_orders()
        api.query_open_orders()

        api.query_all_open_orders()
        api.query_all_open_orders()
        api.query_all_open_orders()
        api.query_all_open_orders()
        # input('wait order:')
        # for o in list(account.orders.values()):
        #     input('cancel:')
        #     api.cancel_order(o)

        # spi = KucoinSwapSpi(key)
        # spi.add_symbol('doge/usdt')

        # def on_ud(ud):
        #     print(ud)
        # account.subscribe(UserEvent.Order, on_ud)

        # def on_deal(order, amount):
        #     print('deal amount:', amount)
        # info = spi.account.info_engine
        # info.subscribe(info.Deal, on_deal)

        while True:
            input(':')

    def try_spi():
        key = keys.get_key('gate_9293')
        spi = KucoinSwapSpi(key)
        acc = spi.account
        # acc.info_engine.show_user_data()
        acc.info_engine.show_problems()

        def on_ud(ud):
            print(ud.data)
        acc.subscribe(UserEvent.Order, on_ud)

        acc.info_engine.show_deal()

        spi.connect_once()
        spi.add_symbol('doge/usdt')

        while True:
            print('-----------orders-----------')
            for i in acc.orders.values():
                print(i)
            input(':')


    fn = KucoinSwapFunctions()
    # a = fn.get_all_ticker()
    # a = [(s, d) for s, d in a.items()]
    # a.sort(key=lambda x: x[1]['vol'], reverse=True)
    # for i in a:
    #     print(i)

    # a = fn.get_recent_trade('btc/usdt.swap')
    # for i in a:
    #     print(i)
    # print("len:", len(a))

    # a = fn.get_all_precision()
    # for i in a.items():
    #     print(i)

    a = fn.get_all_contract_size()
    for s, size in a.items():
        print(s, size, fn.get_value_factor(s))


